package org.benjamin.lending.configuration;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.benjamin.lending.trusteeship.sumapay.SumapayConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

@Configuration
@ComponentScan({"org.benjamin.lending.service","org.benjamin.lending.trusteeship.sumapay"})
@PropertySource(value = {"classpath:jdbc.properties"})
@EnableJpaRepositories(basePackages = "org.benjamin.lending.repository",transactionManagerRef="transactionManager")
public class ApplicationContextConfiguration {
	
	private final Logger logger = LogManager.getLogger();
	
	@Bean
	public SumapayConfig sumapayConfig() {
		return new SumapayConfig("200200200", "0bf845115cf30a177e51454f164a9c89");
	}
	
	@Bean(destroyMethod ="close")
	public BasicDataSource dataSource()  throws PropertyVetoException {
		//准备参数
		String driverClass = "com.mysql.jdbc.Driver";
		String user = "root";
		String password = "huang1100";
		String database = "lending";
		String url = "jdbc:mysql://localhost:3306/";
		String jdbcUrl = url+database;
		
		//使用JDBC创建数据库
		Connection connection = null;
		Statement statement = null;
		try {
			Class.forName(driverClass);
			logger.info("JDBC连接数据库");
			connection = DriverManager.getConnection(url,user,password);
			statement =  connection.createStatement();
			logger.info("正在创建数据库中");
			statement.executeUpdate("create database if not exists "+database);
			logger.info("创建数据库完成");
		}catch(Exception e) {
			logger.error(e.getMessage(),e);
		}finally {
			try {
				if(statement != null) {
					statement.close();
				}
			}catch(Exception e) {
				logger.error(e.getMessage(),e);
			}
			try {
				if(connection != null) {
					connection.close();
				}
			}catch(Exception e) {
				logger.error(e.getMessage(),e);
			}
		}
		
		BasicDataSource dataSource = new BasicDataSource();
		logger.info("加载数据库连接池配置："+driverClass+":"+user+""+password+""+jdbcUrl);
		dataSource.setDriverClassName(driverClass);
		dataSource.setUsername(user);
		dataSource.setPassword(password);
		dataSource.setUrl(jdbcUrl);
		dataSource.addConnectionProperty("zeroDateTimeBehavior", "convertToNull");
		logger.info("数据库连接池配置完毕");
		return dataSource;
	}
	
	@Bean
	public HibernateJpaVendorAdapter jpaVendorAdapter() {
		HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
		jpaVendorAdapter.setShowSql(false);
		jpaVendorAdapter.setGenerateDdl(true);
		jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
		return jpaVendorAdapter;
	}
	
	
	@Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,JpaVendorAdapter jpaVendorAdapter) {
		LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
		entityManagerFactoryBean.setDataSource(dataSource);
		entityManagerFactoryBean.setPackagesToScan("org.benjamin.lending.domain.entity");
		entityManagerFactoryBean.setJpaDialect(new HibernateJpaDialect());
		entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
		Map<String,Object> jpaProperties = new HashMap<>();
		jpaProperties.put("hibernate.format_sql", "true");
		jpaProperties.put("hibernate.hbm2ddl.import_files", "classpath:initial.sql");
		entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
		return entityManagerFactoryBean;
	}
	
	@Bean
	public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(entityManagerFactory);
		return transactionManager;
	}
	
	@Bean
	public ClassLoaderTemplateResolver classLoaderTemplateResolver() {
		ClassLoaderTemplateResolver classLoaderTemplateResolver = new ClassLoaderTemplateResolver();
		classLoaderTemplateResolver.setPrefix("mail/");
		classLoaderTemplateResolver.setTemplateMode("HTML5");
		classLoaderTemplateResolver.setCharacterEncoding("UTF-8");
		return classLoaderTemplateResolver;
	}
	
	@Bean
	public SpringTemplateEngine templateEngine(ClassLoaderTemplateResolver classLoaderTemplateResolver) {
		SpringTemplateEngine templateEngine = new SpringTemplateEngine();
		templateEngine.setTemplateResolver(classLoaderTemplateResolver);
		return templateEngine;
	}
	
	@Bean
	public SimpleMailMessage mailMessage(@Value("${mail.from}")String from) {
		SimpleMailMessage mailMessage = new SimpleMailMessage();
		mailMessage.setFrom(from);
		return mailMessage;
	}
	
	@Bean
	public JavaMailSenderImpl mailSender(@Value("${mail.host}")String host,@Value("${mail.username}")String username,@Value("${mail.password}")String password) {
		JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl();
		mailSenderImpl.setDefaultEncoding("UTF-8");
		mailSenderImpl.setHost(host);
		mailSenderImpl.setUsername(username);
		mailSenderImpl.setPassword(password);
		return mailSenderImpl;
	}

	@Bean
	public JdbcTemplate jdbcTemplate(DataSource dataSource) {
		JdbcTemplate jdbcTemplate = new JdbcTemplate();
		jdbcTemplate.setDataSource(dataSource);
		return jdbcTemplate;
	}
}
